{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Analyzing a double hanger resonator (S Param)\n",
    "### Prerequisite\n",
    "You must have a working local installation of Ansys."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%load_ext autoreload\n",
    "%autoreload 2\n",
    "\n",
    "import qiskit_metal as metal\n",
    "from qiskit_metal import designs, draw\n",
    "from qiskit_metal import MetalGUI, Dict, Headings\n",
    "import pyEPR as epr"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Create the design in Metal\n",
    "Set up a design of a given dimension. Dimensions will be respected in the design rendering.\n",
    "<br>\n",
    "Note the chip design is centered at origin (0,0). "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "design = designs.DesignPlanar({}, True)\n",
    "design.chips.main.size['size_x'] = '2mm'\n",
    "design.chips.main.size['size_y'] = '2mm'\n",
    "\n",
    "gui = MetalGUI(design)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Perform the necessary imports."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.qlibrary.couplers.coupled_line_tee import CoupledLineTee\n",
    "from qiskit_metal.qlibrary.tlines.meandered import RouteMeander\n",
    "from qiskit_metal.qlibrary.qubits.transmon_pocket import TransmonPocket\n",
    "from qiskit_metal.qlibrary.tlines.straight_path import RouteStraight\n",
    "from qiskit_metal.qlibrary.terminations.open_to_ground import OpenToGround"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add 2 transmons to the design."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "options = dict(\n",
    "    # Some options we want to modify from the deafults\n",
    "    # (see below for defaults)\n",
    "    pad_width = '425 um', \n",
    "    pocket_height = '650um',\n",
    "    # Adding 4 connectors (see below for defaults)\n",
    "    connection_pads=dict( \n",
    "        a = dict(loc_W=+1,loc_H=+1), \n",
    "        b = dict(loc_W=-1,loc_H=+1, pad_height='30um'),\n",
    "        c = dict(loc_W=+1,loc_H=-1, pad_width='200um'),\n",
    "        d = dict(loc_W=-1,loc_H=-1, pad_height='50um')\n",
    "    )\n",
    ")\n",
    "\n",
    "## Create 2 transmons\n",
    "\n",
    "q1 = TransmonPocket(design, 'Q1', options = dict(\n",
    "    pos_x='+1.4mm', pos_y='0mm', orientation = '90', **options))\n",
    "q2 = TransmonPocket(design, 'Q2', options = dict(\n",
    "    pos_x='-0.6mm', pos_y='0mm', orientation = '90', **options))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add 2 hangers consisting of capacitively coupled transmission lines."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "TQ1 = CoupledLineTee(design, 'TQ1', options=dict(pos_x='1mm',\n",
    "                                             pos_y='3mm',\n",
    "                                             coupling_length='200um'))\n",
    "TQ2 = CoupledLineTee(design, 'TQ2', options=dict(pos_x='-1mm',\n",
    "                                             pos_y='3mm',\n",
    "                                             coupling_length='200um'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add 2 meandered CPWs connecting the transmons to the hangers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ops=dict(fillet='90um')\n",
    "design.overwrite_enabled = True\n",
    "\n",
    "options1 = Dict(\n",
    "    total_length='8mm',\n",
    "    hfss_wire_bonds = True,\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component='TQ1',\n",
    "            pin='second_end'),\n",
    "        end_pin=Dict(\n",
    "            component='Q1',\n",
    "            pin='a')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "options2 = Dict(\n",
    "    total_length='9mm',\n",
    "    hfss_wire_bonds = True,\n",
    "    pin_inputs=Dict(\n",
    "        start_pin=Dict(\n",
    "            component='TQ2',\n",
    "            pin='second_end'),\n",
    "        end_pin=Dict(\n",
    "            component='Q2',\n",
    "            pin='a')),\n",
    "    lead=Dict(\n",
    "        start_straight='0.1mm'),\n",
    "    **ops\n",
    ")\n",
    "\n",
    "meanderQ1 = RouteMeander(design, 'meanderQ1', options=options1)\n",
    "meanderQ2 = RouteMeander(design, 'meanderQ2', options=options2)\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add 2 open to grounds at the ends of the horizontal CPW."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "otg1 = OpenToGround(design, 'otg1', options = dict(pos_x='3mm', \n",
    "                                                   pos_y='3mm'))\n",
    "otg2 = OpenToGround(design, 'otg2', options = dict(pos_x = '-3mm', \n",
    "                                                   pos_y='3mm', \n",
    "                                                   orientation='180'))\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Add 3 straight CPWs that comprise the long horizontal CPW."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "ops_oR = Dict(hfss_wire_bonds = True,\n",
    "              pin_inputs=Dict(\n",
    "                 start_pin=Dict(\n",
    "                     component='TQ1',\n",
    "                     pin='prime_end'),\n",
    "                 end_pin=Dict(\n",
    "                     component='otg1',\n",
    "                     pin='open')))\n",
    "ops_mid = Dict(hfss_wire_bonds = True,\n",
    "               pin_inputs=Dict(\n",
    "                 start_pin=Dict(\n",
    "                     component='TQ1',\n",
    "                     pin='prime_start'),\n",
    "                 end_pin=Dict(\n",
    "                     component='TQ2',\n",
    "                     pin='prime_end')))\n",
    "ops_oL = Dict(hfss_wire_bonds = True,\n",
    "              pin_inputs=Dict(\n",
    "                 start_pin=Dict(\n",
    "                     component='TQ2',\n",
    "                     pin='prime_start'),\n",
    "                 end_pin=Dict(\n",
    "                     component='otg2',\n",
    "                     pin='open')))\n",
    "\n",
    "cpw_openRight = RouteStraight(design, 'cpw_openRight', options=ops_oR)\n",
    "cpw_middle = RouteStraight(design, 'cpw_middle', options=ops_mid)\n",
    "cpw_openLeft = RouteStraight(design, 'cpw_openLeft', options=ops_oL)\n",
    "\n",
    "gui.rebuild()\n",
    "gui.autoscale()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Eigenmode and Impedance analysis using the `advanced` flow\n",
    "\n",
    "If you are interested in the `recommended` flow, please check the tutorial notebook 4.3. In this section we will use the advanced flow, which directly operates on the simulator thorugh the renderer commands.\n",
    "\n",
    "#### Setup\n",
    "\n",
    "Select the analysis you intend to run from the `qiskit_metal.analyses.simulation` collection.<br>\n",
    "Select the design to analyze and the tool to use for any external simulation."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from qiskit_metal.analyses.simulation.scattering_impedance import ScatteringImpedanceSim\n",
    "em1 = ScatteringImpedanceSim(design, \"hfss\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "For the DrivenModal simulation portion, you can either:\n",
    "1. Use the `em1` user-friendly methods (see tutorial 4.3)\n",
    "2. Control directly the simulation tool from the tool's GUI (outside metal - see specific vendor instructions)\n",
    "3. Use the renderer methods\n",
    "In this section we show the advanced method (method 3).\n",
    "\n",
    "The renderer can be reached from the analysis class. Let's give it a shorter alias."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss = em1.renderer"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we connect to the tool using the unified command."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.start()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Execute simulation and verify convergence\n",
    "\n",
    "Create and activate an eigenmode design called \"HangingResonators\"."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.activate_ansys_design(\"HangingResonators\", 'drivenmodal')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Set the buffer width at the edge of the design to be 0.5 mm in both directions."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.options['x_buffer_width_mm'] = 0.5\n",
    "hfss.options['y_buffer_width_mm'] = 0.5"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### Execute simulation and observe the Impedence\n",
    "Assign lumped ports on the two cpw terminations. Then observe the impedance plots.\n",
    "\n",
    "Here, pins cpw_openRight_end and cpw_openLeft_end are converted into lumped ports with an impedance of 50 Ohms. <br>\n",
    "Neither of the junctions in Q1 or Q2 are rendered."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.render_design(selection=[], \n",
    "                   open_pins=[], \n",
    "                   port_list=[('cpw_openRight', 'end', 50), ('cpw_openLeft', 'end', 50)], \n",
    "                   jj_to_port=[], \n",
    "                   ignored_jjs=[('Q1', 'rect_jj'), ('Q2', 'rect_jj')],\n",
    "                   box_plus_buffer = True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) Captures the renderer GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.save_screenshot()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Create the frequency sweep to observe the impedance, admittance and scattering matrices."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.add_sweep(setup_name=\"Setup\", \n",
    "               name=\"Sweep\", \n",
    "               start_ghz=4.0,\n",
    "               stop_ghz=8.0,\n",
    "               count=2001,\n",
    "               type=\"Interpolating\")"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.analyze_sweep('Sweep', 'Setup')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Plot S, Y, and Z parameters as a function of frequency. <br>\n",
    "The left and right plots display the magnitude and phase, respectively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.plot_params(['S11', 'S21'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.plot_params(['Y11', 'Y21'])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "hfss.plot_params(['Z11', 'Z21'])"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Finally, disconnect from Ansys."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "em1.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "(optional) close the GUI."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# gui.main_window.close()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
